package com.wv.api.service.impl;

import cn.dev33.satoken.util.SaResult;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wv.api.mapper.SysMenuDao;
import com.wv.api.mapper.SysRoleMenuDao;
import com.wv.api.service.ISysMenuService;
import com.wv.common.config.CacheService;
import com.wv.common.constant.RedisConstant;
import com.wv.common.exception.WVException;
import com.wv.common.result.HttpCodeEnum;
import com.wv.common.result.Result;
import com.wv.model.system.SysMenu;
import com.wv.model.system.dto.RoleMenuDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SysMenuServiceImpl implements ISysMenuService {

    @Autowired
    private SysMenuDao dao;

    @Autowired
    private SysRoleMenuDao sysRoleMenuDao;

    @Autowired
    private CacheService cacheService;

    @Override
    public SaResult findAll() {
        List<SysMenu> sysMenus = dao.selectList(null);
        return null;
    }

    @Override
    public SaResult getByUserId(String id) {
        List<SysMenu> sysMenus;
        if (!StringUtils.isEmpty(id)){
            sysMenus = selectByUserId(id);
        }else {
            sysMenus = dao.selectList(null);
        }
        List<SysMenu> orderMenus = TreeMenu(sysMenus);
        return SaResult.ok().setData(orderMenus);
    }

    private List<SysMenu> selectByUserId(String id){
        String s = cacheService.get(RedisConstant.USER_MENU + id);
        if (StringUtils.isEmpty(s)){
            List<SysMenu> list = dao.selectByUserId(id);
            cacheService.set(RedisConstant.USER_MENU+id, JSONUtil.toJsonStr(list));
            return list;
        }
        return JSONUtil.parseArray(s).toList(SysMenu.class);
    }


    @Override
    public SaResult save(SysMenu sysMenu) {
        sysMenu.setCreateTime(LocalDateTime.now());
        return dao.insert(sysMenu) > 0 ? SaResult.ok() : SaResult.error();
    }

    @Override
    public SaResult update(SysMenu sysMenu) {
        sysMenu.setUpdateTime(LocalDateTime.now());
        return dao.updateById(sysMenu) > 0 ? SaResult.ok() : SaResult.error();
    }

    @Override
    public SaResult remove(String[] ids) {
        return dao.deleteBatchIds(Arrays.asList(ids)) > 0 ? SaResult.ok() : SaResult.error();
    }

    @Override
    public Result getMenuByRoleId(String roleId) {
        List<SysMenu> sysMenusPossess = dao.selectByRoleId(roleId);// 当前角色拥有的菜单权限
        sysMenusPossess = TreeMenu(sysMenusPossess);
        ArrayList<SysMenu> child = new ArrayList<>();
        getAllChild(sysMenusPossess,child);
        List<String> collect = child.stream().filter(item -> !"0".equals(item.getParentId())).map(SysMenu::getId).collect(Collectors.toList());
//        List<SysMenu> sysMenus = dao.selectList(null); // 所以的菜单权限
//        Set<String> menuIds = sysMenusPossess.stream().map(SysMenu::getId).collect(Collectors.toSet());
//        for (SysMenu sysMenu : sysMenus) {
//            if (!menuIds.add(sysMenu.getId())) {
//                sysMenu.setRoleIsPossess(true);
//            }
//        }
//        List<SysMenu> list = TreeMenu(sysMenus);
        return Result.ok(collect);
    }

    @Override
    @Transactional
    public Result changeRoleMenu(RoleMenuDto dto) {
        // 删除所有用户的权限key
        cacheService.deletePattern(RedisConstant.USER_PERMISSION+"**");
        cacheService.deletePattern(RedisConstant.USER_MENU+"**");
        // 批量删除
        int i = sysRoleMenuDao.batchDeleteByRoleId(dto.getRoleId());
        // 批量新增
        if (dto.getMenuIds().length > 0){
            int i1 = sysRoleMenuDao.batchInsert(dto.getRoleId(), dto.getMenuIds());
            if (i1 != dto.getMenuIds().length){
                throw new WVException(HttpCodeEnum.ERROR);
            }
        }
        return Result.ok();
    }

    public List<SysMenu> TreeMenu(List<SysMenu> sysMenus){
       return sysMenus.stream().filter(item -> item.getParentId().equals("0"))
                .map(item -> item.setSysMenus(getChild(item.getId(), sysMenus)))
                .sorted(Comparator.comparing(menu -> (menu.getSort() == null ? 0 : menu.getSort())))
                .collect(Collectors.toList());
    }

    public List<SysMenu> getChild(String id,List<SysMenu> sysMenus){
        return sysMenus.stream().filter(item -> Objects.equals(id,item.getParentId()))
                .map(item -> item.setSysMenus(getChild(item.getId(),sysMenus)))
                .sorted(Comparator.comparing(menu -> (menu.getSort() == null ? 0 : menu.getSort())))
                .collect(Collectors.toList());
    }

    public void getAllChild(List<SysMenu> sysMenus,List<SysMenu> res){
        for (SysMenu sysMenu : sysMenus) {
            if (sysMenu.getChildren().size() > 0){
                getAllChild(sysMenu.getChildren(),res);
            }else {
                res.add(sysMenu);
            }
        }
    }

}
